#!/system/bin/sh

#****************************************************
# Author: ZJL
# QQ: 1965786708
# Version: 2.0 beta29
# Date: 2021-2-7 19:00
# FileName: ZJL
# Description: 整合tiny、clnc的免流防跳
#****************************************************

# 防跳版本
readonly zjl_version="2.0 beta29"
readonly zjl_update_date="2021-2-7 19:00"

# 显示帮助 []<-(errorMsg:String)
show_help() {
    # 输出错误消息
    [[ ${1} ]] && echo "\nERROR: ${1}\n"
    
    echo "\n  ****************************************"
    echo "       ********      *****     *"
    echo "             *         *       *"
    echo "           *           *       *"
    echo "         *         *   *       *"
    echo "       ********     ***        ******"
    echo "  ****************************************\n"
    
    echo "  ZJL 防跳 ${zjl_version}，作者: ZJL(龍哥)"
    echo "  更新时间 ${zjl_update_date}"
    echo "  GitHub: https://github.com/EternalPain/ZJL"
    echo "  QQ: 1965786708，发现BUG请加我反馈\n"
    
    echo "  Usage: ZJL [-o/-c]"
    echo "     or: ZJL [-o/-c] [-d]"
    echo "     or: ZJL [-o/-c] [-d] [-i]"
    echo "     or: ZJL [-d]"
    echo "     or: ZJL [-d] [-i]"
    echo "     or: ZJL [-h]"
    echo "     or: ZJL [-v]\n"
    
    echo "  -o or --open         开启防跳"
    echo "  -c or --close        关闭防跳"
    echo "  -d or --display      显示界面"
    echo "  -i or --info         显示所有输出"
    echo "  -h or --help         查看帮助"
    echo "  -v or --version      查看版本\n"
    
    echo "  最多支持三个有效选项:"
    echo "  -o 和 -c 二选一 不可同时选择"
    echo "  -h 和 -v 单独使用 例: ZJL -h"
    
    exit
}


# 读取配置里 = 号后面的内容 [String]<-(arg:String)
get_configure() {
    echo "`echo "${configure_file_content}" | sed -n "s/^${1}=//p"`"
}


# 获取模式指定的的端口 [int]<-(arg:String)
get_confPort() {
    echo "`echo "${mode_listen_port_list}" | grep -w "${1}" | sed "s/.*://" | grep -o "[0-9][0-9]*"`"
}


# 通过包名读取应用UID [int]<-(packageName:String)
get_package_uid() {
    echo "`echo "${package_uid_list}" | grep -wi "${1}" | sed 's/.*[ \t]//'`"
}


# 读取模式及端口 []<-() 
read_mode_port() {
    # 读取模式内容 去除了空行以及//和#开头的内容
    mode_file_content="`sed 's/\/\/.*$//;s/#.*$//;/^[ ]*$/d' ${mode_file}`"
    # 读取模式内带有端口内容的行
    mode_listen_port_list="`echo "${mode_file_content}" | grep "listen"`"
    
    # 判断是否自动识别免流方式
     if [[ ! ${unlimited_data_way} ]]; then
        # 自动识别
        [[ `echo "${mode_file_content}" | grep -E '(^ *user=)|(^ *uid=)'` ]] && unlimited_data_way='tiny' || unlimited_data_way='clnc'
    fi
    
    # 判断核心是否为clnc 模式是否开启UDP
    if [[ "clnc" == ${unlimited_data_way} && `echo "${mode_file_content}" | grep -i "httpUDP"` ]]; then
        # 读取UDP转发端口
        udp_forward_port="`get_confPort udp_tproxy_listen`"
        
        # 判断是否开启代理 UDP
        if [[ ${udp_forward_port} ]]; then
            if [[ ! `grep -q 'TPROXY' /proc/net/ip_tables_targets` ]]; then
                [[ "代理" == ${native_udp} && "放行" != ${release_native_uid} && "禁网" != ${ban_native_uid} ]] && proxy_native_udp="true"
                [[ "代理" == ${hotspot_udp}  && "放行" != ${hotspot_network} && "禁网" != ${hotspot_network} ]] && proxy_hotspot_udp="true"
            else
                is_udp_supported="false"
            fi
        fi
    fi
}


# 开关数据流量 []<-(arg:String)
network_on_off() {
    # 如果没开启[开关数据]功能 就直接退出函数
    [[ ! ${on_off_network} ]] && return 1
    
    [[ "open" == ${1} ]] && svc data enable || svc data disable
}


# 放行本机UID对应的应用 []<-(uid:String)
release_uid() {
    iptables -t nat -I OUTPUT -m owner --uid ${1} -j ACCEPT
    iptables -t mangle -I OUTPUT -m owner --uid ${1} -j ACCEPT
}


# 放行本机指定协议的UID的端口 []<-(protocol:String, uid_ports:String)
release_uid_ports() {
    [[ ! ${2} ]] && return 0
    local uid_ports="`echo "${2}" | sed 's/[ ][ ]*/\n/g' | grep -Ei '^(([0-9]{1,9}|ZJL)(_(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-6][0-5][0-5][0-3][0-5]))((,|:)(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-6][0-5][0-5][0-3][0-5])))*))$'`"
    local uid
    local ports
    local uid_content
    
    for ZJL in ${uid_ports}; do
        if [[ `echo "${ZJL}" | grep '_'` ]]; then
            uid=${ZJL%_*}
            ports=${ZJL#*_}
            
            uid_content=""
            [[ `echo "${uid}" | grep -i '^ZJL$'` ]] || uid_content="-m owner --uid ${uid}"
            
            # 判断手机是否支持 multiport 模块 支持为true
            if [[ ${is_multiport_support} ]]; then
                iptables -t nat -I OUTPUT -p ${1} ${uid_content} -m multiport --dport ${ports} -j ACCEPT
                iptables -t mangle -I OUTPUT -p ${1} ${uid_content} -m multiport --dport ${ports} -j ACCEPT
            else
                ports="`echo ${ports} | sed 's/,/\n/g'`"
                [[ `echo "${ports}" | grep ':'` ]] && ports="`echo "${ports}" | grep -v ':'`"
                
                for ZJL in ${ports}; do
                    iptables -t nat -I OUTPUT -p ${1} ${uid_content} --dport ${ZJL} -j ACCEPT
                    iptables -t mangle -I OUTPUT -p ${1} ${uid_content} --dport ${ZJL} -j ACCEPT
                done
            fi
        else
            uid_content=""
            [[ `echo "${ZJL}" | grep -i '^ZJL$'` ]] || uid_content="-m owner --uid ${ZJL}"
            
            iptables -t nat -I OUTPUT -p ${1} ${uid_content} -j ACCEPT
            iptables -t mangle -I OUTPUT -p ${1} ${uid_content} -j ACCEPT
        fi
    done
}


# 放行共享指定协议的端口 []<-(chain:String, protocol:String, port:int)
release_hotspot_ports() {
    [[ ! ${2} ]] && return 0
    local ports="${2}"
    
    if [[ ${is_multiport_support} ]]; then
        ports="`echo "${ports}" | sed 's/[ ]/,/g'`"
        
        iptables -t mangle -I FORWARD -p ${1} -m multiport --dport ${ports} -j ACCEPT
        iptables -t nat -I PREROUTING -s 192.168/16 -p ${1} -m multiport --dport ${ports} -j ACCEPT
        iptables -t mangle -I PREROUTING -s 192.168/16 -p ${1} -m multiport --dport ${ports} -j ACCEPT
    else
        [[ `echo "${ports}" | grep ':'` ]] && ports="`echo "${ports}" | sed 's/[ ]/\n/g' | grep -v ':'`"
        
        for ZJL in ${ports}; do
        echo 
            iptables -t mangle -I FORWARD -p ${1} --dport ${ZJL} -j ACCEPT
            iptables -t nat -I PREROUTING -s 192.168/16 -p ${1} --dport ${ZJL} -j ACCEPT
            iptables -t mangle -I PREROUTING -s 192.168/16 -p ${1} --dport ${ZJL} -j ACCEPT
        done
    fi
}


# 开机自启 []<-()
boot_auto_on() {
    # 读取配置文件内开启自启填的选项
    local option="`get_configure 开机自启 | grep -Ei '通用|高通|su|面具'`"
    [[ `echo "${option}" | grep -i "^su$"` ]] && option="su"
    
    # 设置实现开启自启文件的路径
    local path="/system/bin/debuggerd"
    # 读取自启文件是否有本核心的开启命令
    [ -f ${path} ] && local read_state="`cat /data/ZJL.sh | grep -w "${0}"`" || local read_state=""
    
    # 选项为 通用 就为true
    if [[ "通用" == ${option} ]]; then
        # 判断自启命令文件是否存在，
        if [ -f ${path}.ori ]; then
             [[ ! ${read_state} ]] && echo "#!/system/bin/sh\nsleep 10\n${0} -o" > /data/ZJL.sh
        else
            # 把 debuggerd 重命名为 debuggerd.ori
            `mv -f ${path} ${path}.ori`
            # 写入内容到 debuggerd 文件
            echo "#!/system/bin/sh\n"\
                  "ZJL() {\n"\
                  "    chmod 777 /data/ZJL.sh\n"\
                  "    /data/ZJL.sh\n"\
                  "}\n"\
                  "ZJL &\n"\
                  "${path}.ori" >${path}
            # 写入防跳路径到状态文件内
            echo "#!/system/bin/sh\nsleep 10\n${0} -o" > /data/ZJL.sh
            # 给三个要用到的文件赋上777权限
            `chmod 777 ${path} ${path}.ori /data/ZJL.sh`
        fi
        
    # 选项不为 通用 且状态文件存在的话，就为true
    elif [[ "通用" != ${option} ]] && [ -f ${path}.ori ]; then
        # 把 debuggerd.ori 重命名为 debuggerd
        `mv -f ${path}.ori ${path}`
        # 给 debuggerd 文件赋权限
        `chmod 755 ${path}`
        # 删除状态文件
        `rm -f /data/ZJL.sh`
    fi
    
    
    # 重写路径，高通自启方法
    path="/system/etc/init.qcom.post_option.sh"
    # 判断所需文件是否存在 存在就读取状态
    [ -f ${path} ] && read_state="`grep -w "${0}" ${path}`" || read_state=""
    
    # 选项为 高通 且状态为关闭的话，就为true
    if [[ "高通" == ${option} && ! ${read_state} ]]; then
        # 写入防跳路径到 init.qcom.post_option.sh 文件内
        [[ `grep 'ZJL' ${path}` ]] && `sed -i '/ZJL/d' ${path}`
        echo "\n${0} -o" >> ${path}
        
    # 选项不为 高通 且状态为开启的话，就为true
    elif [[ "高通" != ${option} && ${read_state} ]]; then
        # 删除 init.qcom.post_option.sh 文件内的防跳路径
        `sed -i '/ZJL/d' ${path}`
    fi
    
    
    # 重写路径，SuperSU自启方法
    local path="/su/su.d/ZJL.sh"
    [ -f ${path} ] && read_state="`cat ${path} | grep -w "${0}"`" || read_state=""
    
    # 选项不为 su 且自启文件不存在的话，就为true
    if [[ "su" == ${option} && ! ${read_state} ]]; then
        # 写入防跳路径到自启文件
        echo "#!/system/bin/sh\nsleep 10\n${0} -o" > ${path}
        # 给权限
        `chmod 777 ${path}`
        
    # 选项不为 su 且自启文件存在的话，就为true
    elif [[ "su" == ${option} ]] && [ -f ${path} ]; then
        # 删除自启文件
        `rm -f ${path}`
    fi
    
    
    # 重写路径，面具自启方法
    if [ ! -d /sbin/.core/img/.core/service.d/ ]; then
        path=/data/adb/service.d/ZJL.sh
    else
        path=/sbin/.core/img/.core/service.d/ZJL.sh
    fi
    [ -f ${path} ] && read_state="`cat ${path} | grep -w "${0}"`" || read_state=""
    
    # 选项为 面具 且自启文件不存在的话，就为true
    if [[ "面具" == ${option} && ! ${read_state} ]]; then
        # 写入防跳路径到自启文件
        echo "#!/system/bin/sh\nsleep 10\n${0} -o" > ${path}
        # 给权限
        `chmod 777 ${path}`
        
    # 选项不为 面具 且文件存在的话，就为true
    elif [[ "面具" != ${option} ]] && [ -f ${path} ]; then
        # 删除自启文件
        `rm -f ${path}`
    fi
}


# 获取指定循环次数的空格 []<-(number:Integer)
become_middle() {
    local product
    local min="1"
    local max="${1}"
    
    while [ ${min} -le ${max} ]; do
        product="${product} "
        ((min++))
    done
    
    echo "${product}"
}


# 输出居中函数 [String]<-(text:String, mode:String)
center_output() {
    local term_width="40"
    
    if [[ ${1} != ${dividing_line} ]]
    then
        local chinese="`echo "${1}" | grep -Eo [^\x00-\xff]+ | sed 's/[[:punct:]]//g;s/ //g'`"
        if [[ ${chinese} ]]; then
            local chinese_length="${#chinese}"
            local english_length="$((${#1} - chinese_length))"
            chinese_length=$((${chinese_length} * 40 / 77))
            local total_width="$((chinese_length + english_length))"
        else
            local total_width="${#1}"
        fi
        #计算次数
        local head_width="$(((term_width - total_width) / 2))"
    else
        local head_width="7"
    fi
        
    # 获取填充的空格
    local head="`become_middle "${head_width}"`"
    
    # 输出处理好的字符串
    case ${2} in
        above)
            echo "\n${head}${1}  "
        ;;
        not_exist)
            echo "${head}${1}  "
        ;;
        below|*)
            echo "${head}${1}\n"
        ;;
    esac
}


# 输出分割线 []<-(mode:String)
output_dividing_line() {
    center_output "${dividing_line}" "${1}"
}


# 获取传入的网卡所使用的流量 []<-(net_card:String)
get_net_card_traffic() {
    # 判断是否存在busybox
    if [[ ${is_busybox_exist} ]]; then
        # 获取网卡使用的流量
        local flow="`ifconfig ${1} | grep -i 'RX bytes' | sed 's/.*RX bytes:.*(\(.*B\)).*TX.*/\1/;s/i.*//'`"
        
        # 输出流量数
        [[ "0.0 B" == ${flow} || ! ${flow} ]] && center_output "已用: 没查到 ×" "above" || center_output "已用: ${flow}  " "above"
    fi
}


# 核心部分的iptables规则 []<-()
important_rules() {
    # 读取的模式 TCP 和 DNS 的转发端口
    if [[ "clnc" == ${unlimited_data_way} ]]; then
        tcp_forward_port="`get_confPort tcp_listen`"
        dns_forward_port="`get_confPort dns_listen`"
    else
        tcp_forward_port="`get_confPort listen_port`"
        dns_forward_port="`get_confPort dns_listen_port`"
    fi
    
    
    # ----- 以下为UDP网络部分规则 -----
    
    # 判断是否开启代理UDP
    if [[ ${proxy_native_udp} || ${proxy_hotspot_udp} ]]; then
        #ip路由        
        ip rule add fwmark 0x4f5da2/0xffffffff table 100
        ip route add local default dev lo table 100
        
        # 判断是否代理本机UDP
        if [[ ${proxy_native_udp} ]]; then
            iptables -t mangle -I OUTPUT -p 17 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
            iptables -t mangle -I OUTPUT -p 17 -j MARK --set-mark 5201314
        fi
        
        # 如果不代理不放行共享UDP的话就禁网
        [[ ! ${proxy_hotspot_udp} && "放行" != ${hotspot_udp} ]] && iptables -t mangle -I PREROUTING -s 192.168/16 -p 17 -j DROP
        
        iptables -t mangle -I PREROUTING ! -i tun+ -p 17 ! --dport 53 -j TPROXY --on-port ${udp_forward_port} --tproxy-mark 5201314
        
        #放行特殊IP段，否则核心做UDP回应会被TPROXY代理造成无限回环或者一些情景下无法工作
        for ZJL in 127/8 10/8 100.64/10 192.168/16 172.16/12 255/8 224/4 240/4 169.254/16; do
            iptables -t mangle -I PREROUTING -d ${ZJL} -j ACCEPT
        done
        
        #放行网卡，否则外网IP可能无法代理UDP
        for ZJL in `ip addr | grep global | grep -E '[1-9]{1}[0-9]{0,2}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sed 's/inet \(.*\)\/.*/\1/'`; do
            iptables -t mangle -I PREROUTING -d ${ZJL} -j ACCEPT
        done
    fi
    
    
    # ----- 以下为本机网络部分规则 -----
    
    # 判断本机网络是否为代理或者禁网
    if [[ "放行" != ${release_native_uid} ]]; then
        # 禁mengle链
        iptables -t mangle -P OUTPUT DROP
        # 禁网内核
        iptables -t mangle -I OUTPUT -m owner ! --uid 0-99999999 -j DROP || iptables -t mangle -I OUTPUT -m owner ! --uid 0-99999 -j DROP
        
        if [[ "禁网" != ${ban_native_uid} ]]; then
            # 放行TCP和DNS
            iptables -t mangle -I OUTPUT -p 6 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
            [[ "禁网" != ${native_dns} ]] && iptables -t mangle -I OUTPUT -p 17 --dport 53 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
            
            # 如果不代理UDP就执行本条
            [[ ! ${proxy_native_udp} ]] && iptables -t nat -I OUTPUT -j REDIRECT
            # 转发 TCP
            iptables -t nat -I OUTPUT -p 6 -j REDIRECT --to ${tcp_forward_port}
            # 判断本机DNS是否为代理
            if [[ "放行" != ${native_dns} && "禁网" != ${native_dns} ]]; then
                local custom_native_dns="`echo ${native_dns} | grep -Ew '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'`"
                # 判断是否为自定义DNS
                if [[ ${custom_native_dns} ]]; then
                    iptables -t nat -I OUTPUT -p 17 --dport 53 -j DNAT --to ${custom_native_dns}
                else
                    iptables -t nat -I OUTPUT -p 17 --dport 53 -j REDIRECT --to ${dns_forward_port}
                fi
            fi
            
            # 放行核心 GID 或 UID
            local uid_or_gid
            [[ "tiny" == ${unlimited_data_way} ]] \
                && uid_or_gid="--uid ${forward_uid}" \
                || uid_or_gid="--gid 3004"
            iptables -t nat -I OUTPUT -m owner ${uid_or_gid} -j ACCEPT
        fi
    fi
    
    
    # ----- 以下为共享网络部分规则 -----
    
    # 判断共享网络是否为代理或者禁网
    if [[ "放行" != ${hotspot_network} ]]; then
        # 禁网 FORWARD 链
        iptables -t mangle -P FORWARD DROP
        # 判断是否禁止共享ipv6
        [[ "放行" != ${ipv6_network} ]] && ip6tables -t mangle -P FORWARD DROP
        
        # 判断共享网络是否为代理
        if [[ "禁网" != ${hotspot_network} ]]; then
            # 共享网络规则
            iptables -t mangle -I PREROUTING -s 192.168/16 -m state --state INVALID -j DROP
            
            # 如果不代理UDP就执行本条
            [[ ! ${proxy_hotspot_udp} ]] && iptables -t nat -I PREROUTING -s 192.168/16 ! -d 192.168/16 -j REDIRECT
            
            # 转发 TCP
            iptables -t nat -I PREROUTING -s 192.168/16 -p 6 ! -d 192.168/16 -j REDIRECT --to ${tcp_forward_port}
            # 判断共享DNS是否为禁网
            if [[ "禁网" == ${hotspot_dns} ]]; then
                iptables -t mangle -I PREROUTING -s 192.168/16 -p 17 --dport 53 -j DROP
            else
                # 判断共享DNS是否为代理
                if [[ "放行" != ${hotspot_dns} ]]; then
                    [[ "tiny" == ${unlimited_data_way} ]] \
                        && iptables -t nat -I PREROUTING -s 192.168/16 -p 17 --dport 53 -j REDIRECT --to 53 \
                        || iptables -t nat -I PREROUTING -s 192.168/16 -p 17 --dport 53 -j REDIRECT --to ${dns_forward_port}
                fi
            fi
        fi
    fi
    
    # 放行本机网卡
    for ZJL in $(get_configure 放行网卡); do
        iptables -t nat -I OUTPUT -o ${ZJL} -j ACCEPT
        iptables -t mangle -I OUTPUT -o ${ZJL} -j ACCEPT
    done
    
    iptables -t nat -I OUTPUT -d 192.168/16 -j ACCEPT
    iptables -t mangle -I OUTPUT -d 192.168/16 -j ACCEPT
}


# 游戏流量规则 []<-()
game_rules() {
    # 读取游戏配置
    local games="`get_configure 本机游戏`"
    # 代理则返回
    [[ ! `echo ${games} | grep -Ei "^(放行UID|放行UDP|禁网)$"` ]] && return
    
    # 预设一个局部变量存游戏UID
    local uid
    
    # 游戏包名 游戏列表：王者荣耀、QQ飞车、CF、和平精英、使命召唤、火影忍者、第五人格网易版、明日之后网易版、球球大作战
    for ZJL in com.tencent.tmgp.sgame \
               com.tencent.tmgp.speedmobile \
               com.tencent.tmgp.cf \
               com.tencent.tmgp.pubgmhd \
               com.tencent.tmgp.cod \
               com.tencent.KiHan \
               com.netease.mrzh \
               com.netease.dwrg \
               com.ztgame.bob; do
        uid="`get_package_uid ${ZJL}`"
        [[ ! ${uid} ]] && continue
        
        if [[ `echo "${games}" | grep -i "^放行UID$"` ]]; then
            release_uid "${uid}"
        elif [[ "禁网" == ${games} ]]; then
            iptables -t mangle -I OUTPUT -m owner --uid ${uid} -j DROP
        else
            iptables -t nat -I OUTPUT -p 17 -m owner --uid ${uid} -j ACCEPT
            iptables -t mangle -I OUTPUT -p 17 -m owner --uid ${uid} -j ACCEPT
        fi
    done
}


# 次要部分的iptables规则 []<-()
not_important_rules() {
    # ----- 以下为本机网络部分规则 -----
    
    # 读取包名和uid列表
    package_uid_list="`sed -r 's/([^ ]*) ([0-9]*) .*/\1 \2/g' /data/system/packages.list`"
    # 游戏iptables规则
    game_rules
    
    # 放行本机UID对应的应用
    if [[ "放行" != ${release_native_uid} ]]; then
        for ZJL in ${release_native_uid}; do
            release_uid "${ZJL}"
        done
    fi
    
    # 禁止本机UID对应的软件的网
    if [[ "禁网" != ${ban_native_uid} ]]; then
        for ZJL in ${ban_native_uid}; do
            iptables -t mangle -I OUTPUT -m owner --uid ${ZJL} -j DROP
        done
    fi
    
    # 判断是否放行本机UDP
    if [[ "放行" == ${native_udp} ]]; then
        iptables -t nat -I OUTPUT -p 17 -j ACCEPT
        iptables -t mangle -I OUTPUT -p 17 -j ACCEPT
    fi
    
    # 放行本机UID对应的软件的UDP
    for ZJL in `get_configure 放行UDP`; do
        iptables -t nat -I OUTPUT -m owner --uid ${ZJL} -p 17 -j ACCEPT
        iptables -t mangle -I OUTPUT -m owner --uid ${ZJL} -p 17 -j ACCEPT
    done
    
    local release_native_https="`get_configure 放行HTTPS`"
    # 放行本机HTTPS
    if [[ "放行" == ${release_native_https} ]]; then
        iptables -t nat -I OUTPUT -p 6 --dport 443 -j ACCEPT
        iptables -t mangle -I OUTPUT -p 6 --dport 443 -j ACCEPT
        
    else
        # 放行本机UID对应的软件的HTTPS
        for ZJL in `echo "${release_native_https}" | grep -o [0-9][0-9]*`; do
            iptables -t nat -I OUTPUT -p 6 --dport 443 -m owner --uid ${ZJL} -j ACCEPT
            iptables -t mangle -I OUTPUT -p 6 --dport 443 -m owner --uid ${ZJL} -j ACCEPT
        done
    fi
    
    # 根据包名放行本机UID对应的软件的流量
    for ZJL in `get_configure 放行包名`; do
        for uid in `get_package_uid ${ZJL}`; do
            [[ ! ${uid} ]] && continue || release_uid "${uid}"
        done
    done
    
    # 放行（QQ && TIM && 微信）的 UDP 8000 端口，为网络电话使用的端口
    if [[ "放行" == "`get_configure QQ微信电话`" ]]; then
        for ZJL in tencent.mobileqq tencent.tim tencent.mm; do
            uid=`get_package_uid ${ZJL}`
            [[ ! ${uid} ]] && continue
            
            iptables -t nat -I OUTPUT -p 17 --dport 8000 -m owner --uid ${uid} -j ACCEPT
            iptables -t mangle -I OUTPUT -p 17 --dport 8000 -m owner --uid ${uid} -j ACCEPT
        done
    fi
    
    # 放行本机TCP端口
    release_uid_ports "6" "`get_configure 放行TCP端口`"
    # 放行本机UDP端口
    release_uid_ports "17" "`get_configure 放行UDP端口`"
    
    # 判断是否放行本机DNS
    [[ "放行" == ${native_dns} ]] && iptables -t nat -I OUTPUT -p 17 --dport 53 -j ACCEPT
    
    
    # ----- 以下为共享网络部分规则 -----
    
    # 判断是否放行共享UDP
    if [[ "放行" == ${hotspot_udp} ]]; then
        iptables -t mangle -I FORWARD -p 17 -j ACCEPT
        iptables -t nat -I PREROUTING -s 192.168/16 -p 17 -j ACCEPT
    fi
    
    hotspot_https="`get_configure 共享HTTPS`"
    if [[ "放行" == ${hotspot_https} ]]; then
        iptables -t mangle -I FORWARD -p 6 --dport 443 -j ACCEPT
        iptables -t nat -I PREROUTING -s 192.168/16 -p 6 --dport 443 -j ACCEPT
        
    elif [[ "禁网" == ${hotspot_https} ]]; then
        iptables -t mangle -I PREROUTING -s 192.168/16 -p 6 --dport 443 -j DROP
    fi
    
    # 放行共享TCP端口
    release_hotspot_ports "6" "`get_configure 共享TCP端口`"
    
    # 放行共享UDP端口
    release_hotspot_ports "17" "`get_configure 共享UDP端口`"
}


# 初始化 [Boolean]<-()
init_zjl() {
    # 模块路径
    module_path="${0%/*}"
    # 防跳路径
    zjl_path="${module_path%/*}"
    # 模式路径
    mode_path="${zjl_path}"
    
    # 切换当前路径为防跳路径
    cd ${zjl_path}
    
    # 处理模块路径括号问题
    local processed_module_path="${module_path}"
    for ZJL in '(' ')' '（' '）';do
        processed_module_path="${processed_module_path//${ZJL}/\\${ZJL}}"
    done
    
    # 判断模块文件夹是否存在busybox 没有将使用系统的
    [ -s ${module_path}/busybox ] && alias busybox="${processed_module_path}/busybox"
    
    # 判断模块文件夹是否存在MLBox
    if [ -s ${module_path}/MLBox ]; then
        alias MLBox="${processed_module_path}/MLBox"
        is_MLBox_exist="true"
    fi
    
    # 脚本运行所需命令
    local command_requireds="mv rm ip ps sed find grep pkill pgrep chmod ifconfig"
    # 防跳配置文件路径
    local ini_path="${zjl_path%/*}/.ZJL.ini"
    
    # 判断是否存在busybox
    if [[ `busybox --help` ]]; then
        for ZJL in ${command_requireds}; do
            # 设置命令别名
            alias ${ZJL}="busybox ${ZJL}"
        done
        
        # 表示当前脚本找到了busybox
        is_busybox_exist="true"
        `rm -f ${ini_path}`
    else
        # 表示当前脚本找不到busybox，将使用系统自带命令
        
        # 读取是否存在配置文件
        if [[ ! `grep "command=" ${ini_path}` ]]; then
            command_requireds="mv rm ip sed find grep pkill pgrep chmod"
            # 读取系统是否存在脚本运行所需命令 如果有一个命令不存在就退出脚本
            if [[ `type ${command_requireds} | grep not found` ]]; then
                # 输出提示
                echo "\n      __________________________\n\n"\
                      "              ZJL 2.0\n\n"\
                      "          无busybox启动失败\n"\
                      "     __________________________\n\n"\
                      "         手机需内置以下命令\n\n"\
                      "           mv rm ip sed \n\n"\
                      "          find grep pkill\n\n"\
                      "         kill pgrep chmod\n\n"\
                      "         所以请安装busybox\n\n"\
                      "        或复制到模块文件夹里\n"\
                      "     __________________________"
                # 退出函数
                return 1
            fi
            
            # 如果命令都存在，则写入配置文件
            echo "command=\"ON\"" > ${ini_path}
            # 文件赋权限
            `chmod 777 ${ini_path}`
        fi
    fi
    
    for ZJL in ${zjl_path} ${mode_path} ${module_path}; do
        # 删除bak后缀备份文件
        `rm -f ${ZJL}/*.bak`
        # 赋予文件权限
        `chmod -R 777 ${ZJL}`
    done
    
    if [[ 'iptables: No chain/target/match by that name' != `iptables -t nat -I OUTPUT -p 17 -m multiport --dport 12345 -j ACCEPT 2>&1` ]]; then
        iptables -t nat -D OUTPUT -p 17 -m multiport --dport 12345 -j ACCEPT
        is_multiport_support="true"
    fi
    
    # 读取防跳配置文件，并过滤以 // 和 # 为开头的注释内容
    configure_file_content="`sed 's/\/\/.*$//;s/#.*$//;/^[ ]*$/d;s/[[:space:]][[:space:]]*/ /g;s/^ //g;s/ $//g;s/= /=/g' ${zjl_path}/*.ini`"
    
    # 读取配置
    release_native_uid="`get_configure 放行UID`"
    ban_native_uid="`get_configure 禁网UID`"
    native_udp="`get_configure 本机UDP`"
    native_dns="`get_configure 本机DNS`"
    hotspot_network="`get_configure 共享网络 | grep -Ei "放行|禁网"`"
    hotspot_udp="`get_configure 共享UDP`"
    hotspot_dns="`get_configure 共享DNS`"
    unlimited_data_way="`get_configure 免流方式 | grep -Ewi '^tiny|clnc$'`"
    select_mode_file="`get_configure 选择模式`"
    ipv6_network="`get_configure 手机IPv6`" 
    check_extranet_way="`get_configure 检测联网 | grep -Ei "^[abcd]$"`"
    check_extranet_udp="`get_configure 检测UDP联网 | grep -w '开启'`"
    quickly_open_scripts="`get_configure 快速启动 | grep -w '开启'`"
    on_off_network="`get_configure 开关数据 | grep -w '开启'`"
    
    # 读取免流方式
    if [[ ${unlimited_data_way} ]]; then
        [[ `echo "${unlimited_data_way}" | grep -wi '^tiny$'` ]] && unlimited_data_way='tiny' || unlimited_data_way='clnc'
    fi
    
    # 查看模式文件状态，正常为空
    if [[ `find "${mode_path}" -type f -maxdepth 1 -iname "*.conf"` ]]; then
        # 判断是否指定了模式名
        if [[ ${select_mode_file} ]]; then
            mode_file="${select_mode_file}.conf"
            # 判断是否找到配置里选择的模式文件
            [[ ! `find "${mode_path}" -type f -maxdepth 1 -name "${mode_file}"` ]] && mode_file_state="no_selected_mode_file"
        else
            mode_file="*.conf"
            # 判断是否有多个模式文件
            [ 1 -lt `find "${mode_path}" -type f -maxdepth 1 -iname "${mode_file}" | grep -c ".conf$"` ] && mode_file_state="please_select"
        fi
        
        if [[ ! ${mode_file_state} ]]; then
            # 判断模式文件有没有内容，有就为正常
            if [ ! -s ${mode_path}/${mode_file} ]; then
                mode_file_state="no_content"
            else
                mode_file_state="normal"
                # 模式正常就重写模式路径
                mode_file="`find "${mode_path}" -type f -maxdepth 1 -name "${mode_file}"`"
                
                # 如果执行检测.sh就读取端口
                [[ ! ${script_execution_state} ]] && read_mode_port
            fi
        fi
    else
        # 没找到模式文件
        mode_file_state="no_mode_file"
    fi
    
    return 0
}


# 关闭防跳 []<-()
close_zjl() {
    sleep 0.1
    # 关闭核心    
    `pkill tiny`
    `pkill clnc`
    
    # 清理ip路由规则
    ip rule del fwmark 0x4f5da2/0xffffffff table 100
    ip route del local default dev lo table 100
    
    # 解除禁止本机ipv6
    ip -6 rule del pref 13001 unreachable
    
    # 清除iptables规则        
    iptables -t nat -F OUTPUT
    iptables -t nat -F PREROUTING
    iptables -t mangle -F PREROUTING
    
    for ZJL in OUTPUT FORWARD; do
        iptables -t mangle -F ${ZJL}
        iptables -t mangle -P ${ZJL} ACCEPT
    done
    
    # 解除禁止共享ipv6
    ip6tables -t mangle -P FORWARD ACCEPT
    
    # 释放网络
    iptables -D OUTPUT ! -o wlan+ -j DROP
    iptables -D FORWARD -j DROP
    iptables -D OUTPUT ! -o wlan+ -m owner ! --gid 3004 -j DROP
        
    # 调用开机自启函数
    boot_auto_on
}


# 开启防跳 [Boolean]<-()
open_zjl() {
    # 如果模式为不正常，就退出函数
    [[ "normal" != ${mode_file_state} ]] && return 1
    
    # 读取模式及端口
    read_mode_port
    
    # 获取GID 启动核心
    if [[ 'clnc' == "${unlimited_data_way}" ]]; then
        [[ ${on_off_network} ]] && sleep 0.2
        # 禁止网络 改为放行GID
        iptables -D OUTPUT ! -o wlan+ -j DROP
        iptables -I OUTPUT ! -o wlan+ -m owner ! --gid 3004 -j DROP
        
        local temp_mode_file="/dev/${mode_file##*/}"
        # 处理模式 删除Tun部分 写入临时模式文件
        echo -E "`sed '/tunDevice/d' ${mode_file}`" > ${temp_mode_file}
       
        # 设置 clnc初始化配置DNS
        export CLNC_INIT_CONFIG_DNS="`getprop net.dns1`"
        CLNC_INIT_CONFIG_DNS="${CLNC_INIT_CONFIG_DNS:-'119.29.29.29'}"
        
        # 以GID方式 启动clnc核心
        core_start_error_info="`${module_path}/clnc -g 3004 -c ${temp_mode_file} 2>&1`"
        # 删除临时模式文件
        `rm -f ${temp_mode_file}`
    else
        forward_uid="`echo "${mode_file_content}" | grep -Ew '(^ *user)|(^ *uid)' | sed -rn 's/[ ][ ]*//g;s/;//g;s/root/0/;s/inet/3003/;s/net_raw/3004/;s/.*=([0-9]+)/\1/;$p'`"
        forward_uid=${forward_uid:-"0"}
        
        # 以UID方式 启动tiny核心
        core_start_error_info="`${module_path}/tiny -c ${mode_file} 2>&1`"
    fi
    
    # 如果核心没开启，就退出函数
    [[ ! `pgrep /${unlimited_data_way}` ]] && return 2
    
    # 打开ipv4路由转发
    echo '1' > /proc/sys/net/ipv4/ip_forward
    echo '1' > /proc/sys/net/ipv4/ip_dynaddr
    
    # 关闭selinux
    setenforce 0
    
    # 判断是否启动TCP_FASTOPEN
    [[ "clnc" == ${unlimited_data_way} && `echo "${mode_file_content}" | grep '^ *tcp_option *= *TFO'` ]] && echo '3' >/proc/sys/net/ipv4/tcp_fastopen
    
    # 通过ip路由禁止本机ipv6
    [[ "放行" != ${ipv6_network} ]] && ip -6 rule add pref 13001 unreachable
    
    # 执行核心部分的iptables规则
    important_rules
    # 执行次要部分的iptables规则
    not_important_rules
    
    return 0
}


# 解析json 获取 key 对应的 value(此函数不适于有多个 key 一样的) [String]<-(json:String, key:String)
get_json_value(){
    echo "${1//\"/}" | sed "s/.*$2:\([^,}]*\).*/\1/"
}


# 检测联网 []<-(time_out:Integer)
detect_internet_connectivity() {
    # 超时时间(单位秒)
    [[ ${1} ]] && local time_out="${1}" || local time_out="2"
    
    # 判断是否开启检测联网功能
    if [[ ${check_extranet_way} ]]; then
        # 通过MLBox检测网络连接
        case ${check_extranet_way} in
            a|A)
                # 淘宝 的接口
                extranet_ip="`MLBox -http='http://ip.taobao.com/outGetIpInfo?ip=myip&accessKey=alibaba-inc' -t=${time_out}`"
                [[ "0" == `get_json_value "$extranet_ip" "code"` ]] \
                    && extranet_ip="IP：`get_json_value "$extranet_ip" "queryIp"`\n来自：`get_json_value "$extranet_ip" "country"``get_json_value "$extranet_ip" "region"``get_json_value "$extranet_ip" "city"` `get_json_value "$extranet_ip" "isp"`" \
                    || extranet_ip=""
            ;;
            b|B)
                # 站长之家 的接口
                extranet_ip="`MLBox -http="http://mip.chinaz.com/" -t=${time_out} | grep -Ei '您的IP|数据一' \
                             | sed 's/<[^>]*>//g;s/.*地址：/IP：/;s/.*数据一：/来自：/'`"
            ;;
            c|C)
                # ipip.net 的接口
                extranet_ip="`MLBox -http="http://myip.ipip.net/" -t=${time_out} | grep -E 'IP|来自' \
                             | sed 's/.*IP：/IP：/;s/来自于：/\n来自：/;s/| //'`"
            ;;
        esac
        
        # 判断HTTP是否联网成功
        if [[ ${extranet_ip} ]]; then
            # 去除前后空格
            extranet_ip="`echo "${extranet_ip}" | sed "s/^[ \t]*//g;s/[ \t]*$//g"`"
            extranet_http="√"
            # HTTP联网成功了才检测HTTPS
            [[ ! `MLBox -http="https://im.qq.com/favicon.ico" -t=${time_out} | grep -Ei "timeout|httpGetResponse"` ]] && extranet_https="√"
        fi
    fi
    
    # 判断是否开启检测UDP
    if [[ ${check_extranet_udp} ]] && [[ ( ! ${check_extranet_way} ) || "√" == ${extranet_http} ]] && [[ ${proxy_native_udp} || ${proxy_hotspot_udp} ]]; then
        [[ "UDP network is smooth" == `MLBox -udptest=true -t=${time_out}` ]] && extranet_udp="√" || extranet_udp="×"
    fi
}


# 显示输出界面 []<-()
show_display() {
    # 分割线
    dividing_line="__________________________"
    
    # 输出两个空行
    echo "\n"
    
    output_dividing_line
    center_output "ZJL 2.0 " "not_exist"
    [[ ! ${is_busybox_exist} ]] && center_output "无 BusyBox 使用  " "above"
    [[ ${is_udp_supported} ]] && center_output "本机不支持 UDP 代理  " "above"
    [[ ! ${is_multiport_support} ]] && center_output "本机不支持放行端口范围  " "above"
    output_dividing_line
    
    local core_state
    # 检测当前使用的免流核心状态
    if [[ `pgrep /tiny` ]]; then
        core_state="tiny"
    elif [[ `pgrep /clnc` ]]; then
        core_state="clnc"
    fi
    
    # 输出当前使用的免流核心状态
    if [[ ${core_state} ]]; then
        center_output "核心: ${core_state} √  " "not_exist"
    else
        center_output "核心: 啥都没开 ×   " "not_exist"
        
        # 没开免流关闭检测网络
        check_extranet_way=""
        check_extranet_udp=""
        
        if [[ ${core_start_error_info} ]]; then
            output_dividing_line "not_exist"
            center_output "开启失败的错误信息:   " "above"
            
            echo "${core_start_error_info}" | while read ZJL; do
                center_output "${ZJL}" "above"
            done
        fi
    fi
    
    # 判断当前模式是否正常
    if [[ "normal" == ${mode_file_state} ]]; then
        # 判断核心是否开启
        if [[ ${core_state} ]]; then
            # 输出模式名
            if [[ ${is_busybox_exist} ]]; then
                center_output "模式: `ps w | grep "${core_state}" | grep -o '\-c.*' | sed -rn 's/.*\/(.*)/\1/;1p'`  " "above"
            elif [[ ${select_mode_file} ]]; then
                center_output "模式 ${select_mode_file}.conf  " "above"
            fi
        fi
    elif [[ ${mode_file_state} ]]; then
        output_dividing_line
        
        # 输出模式文件当前状态
        case ${mode_file_state} in
            no_selected_mode_file)
                center_output "没找到 ${select_mode_file}.conf  "
                center_output "请去 [选择模式] 里重填 !  " "not_exist"
            ;;
            please_select)
                find "${mode_path}" -type f -maxdepth 1 -iname "*.conf" | while read ZJL; do
                    center_output "模式: ${ZJL##*/}  "
                done
                center_output "请使用 [选择模式] 功能 !  " "not_exist"
            ;;
            no_content)
                center_output "模式内容为空 ! " "not_exist"
            ;;
            no_mode_file)
                center_output "请添加模式 ! " "not_exist"
            ;;
        esac
    fi
    
    # 判断是否开启快速启动功能
    if [[ ! ${quickly_open_scripts} ]]; then
        output_dividing_line
        # 获取WIFI的网卡
        local wifi_net_card="`getprop wifi.interface`"
        wifi_net_card="${wifi_net_card:-"`dumpsys connectivity | grep 'NetworkAgentInfo{' | grep -wi 'type: WIFI' | grep -o 'InterfaceName: [^ ]*' | sed 's/.*InterfaceName: //'`"}"
        wifi_net_card="${wifi_net_card:-"`dumpsys netstats | grep -i "iface" | grep -w "type=WIFI" | sed -n 's/.*iface=\(.*\) ident.*/\1/g;1p'`"}"
        wifi_net_card="${wifi_net_card:-"`ip route | grep -oi 'wlan[^ ]*'`"}"
        
        # 获取网络信息
        local netstats_info="`dumpsys connectivity | grep 'NetworkAgentInfo{' | grep -w 'type: WIFI'`"
        
        # 判断是否开启WiFi
        local is_wifi_open=`echo "${netstats_info}" | sed -r 's/.*type: (.*), state.*/\1/g'`
        
        if [[ ${is_wifi_open} ]]; then
            center_output "网络: WIFI 已连接 √  "
            # 获取WiFi SSID
            local wifi_name="`dumpsys netstats | grep -i "iface" | grep -w "type=WIFI" | sed -n 's/.*networkId="\(.*\)".*/\1/g;1p'`"
            
            if [[ ${wifi_name} ]]; then
                # 输出 WiFi名字
                center_output "名称: ${wifi_name}  " "not_exist"
                
                # 获取WiFi密码
                local wifi_password
                if [ -s /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml ]; then
                    wifi_password="`grep -wA 3 '<string name="SSID">&quot;'${wifi_name}'' /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml \
                                    | sed -n 's/.*<string name="PreSharedKey">&quot;\(.*\)&quot.*/\1/p'`"
                elif [ -s /data/misc/wifi/WifiConfigStore.xml ]; then
                    wifi_password="`grep -wA 3 '<string name="SSID">&quot;'${wifi_name}'' /data/misc/wifi/WifiConfigStore.xml \
                                    | sed -n 's/.*PreSharedKey">&quot;\(.*\)&quot.*/\1/p'`"
                elif [ -s /data/misc/wifi/wpa_supplicant.conf ]; then
                    wifi_password="`grep -wA 3 'ssid="'${wifi_name}'"' /data/misc/wifi/wpa_supplicant.conf \
                                    | sed -n 's/.*psk="\(.*\)".*/\1/p'`" 
                fi
                
                # 输出 WiFi密码
                if [[ ${wifi_password} ]]; then
                    center_output "密码: ${wifi_password}  " "above"
                fi
            else
                center_output "获取WiFi名和密码失败  " "not_exist"
            fi
            
            # 输出 WiFi 使用流量数
            get_net_card_traffic "${wifi_net_card}"
            
        else
            # ———当前使用的是流量———
            
            # 获取流量网卡
            local net_card="`dumpsys connectivity | grep 'NetworkAgentInfo{' | grep 'type: MOBILE' | grep -Ev '(extra: ims)|(extra: IMS)' | grep -o 'InterfaceName: [^ ]*' | sed 's/.*InterfaceName: //'`"
            net_card="${net_card:-"`dumpsys netstats | grep -i 'iface=' | grep 'metered=true' | grep -Eio -m 1 'rmnet[^ ]*|ccmni[^ ]*'`"}"
            net_card="${net_card:-"`ip route | grep -Eio -m 1 'rmnet[^ ]*|ccmni[^ ]*'`"}"
            
            # 获取内网IP
            [[ ${net_card} ]] && local intranet_ip="`ip -4 addr | grep -w ${net_card} | sed -rn 's/.*inet (.*)\/.*/\1/p'`"
            
            # 判断是否能读取到流量内网IP
            if [[ ${intranet_ip} ]]; then
                # 输出内网IP
                center_output "内网: ${intranet_ip} "
                
                # 只有执行开启和检测的时候 开启了检测功能才会开始检测网络
                if [[ "close" != ${script_execution_state} ]] && [[ ${check_extranet_way} || ${check_extranet_udp} ]]; then
                    local check_extranet_state="ON"
                    # 判断是否存在MLBox模块
                    [[ ${is_MLBox_exist} ]] && detect_internet_connectivity "2" || check_extranet_state="MLBoxNoExist"
                fi
                
                # 重新获取网络信息
                netstats_info="`dumpsys connectivity | grep 'NetworkAgentInfo{' | grep -Ev 'ims|IMS|tun|TUN|wifi|WIFI'`"
                # 获取 APN
                local apn="`echo "${netstats_info}" | sed 's/.*extra: \([^,]*\),.*/\1/'`"
                # 获取APN 代理和端口 信息
                local apn_agent_and_port="`echo "${netstats_info}" | sed -rn 's/.*HttpProxy: \[(.*)\] ([0-9]{2,5}).*/\1 \2/p'`"
                # 输出接入点
                [[ ${apn_agent_and_port} ]] && center_output " APN: ${apn} ${apn_agent_and_port}" "not_exist" || center_output "APN: ${apn} 代理留空   " "not_exist"
                
                
                # 输出数据使用流量数
                get_net_card_traffic "${net_card}"
                
                # 判断检测联网状态
                case ${check_extranet_state} in
                    ON)
                        # 判断是否开启检测联网功能
                        if [[ ${check_extranet_way} ]]; then
                            output_dividing_line
                            center_output "HTTP 联网 ${extranet_http:="×"}   HTTPS 联网 ${extranet_https:="×"}  " "not_exist"
                                            
                            if [[ ${extranet_ip} ]]; then
                                echo "${extranet_ip}" | while read ZJL; do
                                    center_output "${ZJL}  " "above"
                                done
                            else
                                center_output "查询外网IP失败    "  "above"
                            fi
                        fi
                        
                        # 判断是否检测了UDP
                        if [[ ${extranet_udp} ]]; then
                            output_dividing_line
                            center_output "UDP 连接 ${extranet_udp} " "not_exist"
                        fi
                    ;;
                    MLBoxNoExist)
                        output_dividing_line
                        center_output "[检测联网]和[检测UDP联网]需要MLBox     "
                        center_output "请将MLBox模块复制进模块文件夹  " "not_exist"
                    ;;
                esac
                
            else
                center_output "网络: 数据都没开 ×  " "not_exist"
            fi
            
            # 获取热点网卡
            local hotspots_net_card="`ip route | grep -Eio "${wifi_net_card}|wlan.|ap.|softap."`"
            # 判断热点是否开启
            if [[ ! ${is_wifi_open} && ${hotspots_net_card} ]] || [[ ${is_wifi_open} && `echo "${hotspots_net_card}" | grep -v "${wifi_net_card}"` ]]; then
                output_dividing_line
                # 判断是否同时开WiFi和热点                               
                [[ ${is_wifi_open} ]] && hotspots_net_card="`echo "${hotspots_net_card}" | sed "/${wifi_net_card}/d"`"
                # 获取热点连接数
                local hotspots_connect="`grep '0x2' /proc/net/arp | grep -c "${hotspots_net_card}"`"
                # 获取热点连接设备数
                center_output "热点: ${hotspots_connect} 个已连接   "
                
                # 获取热点的名字和密码
                if [ -s /data/misc/apexdata/com.android.wifi/WifiConfigStoreSoftAp.xml ]; then
                    local hotspot="`grep -E '(<string name="SSID">)|(<string name="Passphrase">)' /data/misc/apexdata/com.android.wifi/WifiConfigStoreSoftAp.xml`"
                    local hotspot_name="`echo "${hotspot}" | sed -n 's/.*name="SSID">\(.*\)<\/string>.*/\1/p'`"
                    local hotspot_password="`echo "${hotspot}" | sed -n 's/.*name="Passphrase">\(.*\)<\/string>.*/\1/p'`"
                elif [ -s /data/misc/wifi/softap.conf ]; then
                    local hotspot="`sed -r $'s/\u0004/\u00A0/;s/[\u0001-\u0019]//g' /data/misc/wifi/softap.conf`"
                    local hotspot_name="`echo ${hotspot} | sed $'s/\u00A0.*//'`"
                    local hotspot_password="`echo ${hotspot} | sed $'s/.*\u00A0//'`"
                fi
                
                # 输出热点信息
                if [[ ${hotspot_name} ]]; then
                    center_output "名称: ${hotspot_name}  " "not_exist"
                    [[ ${hotspot_password} ]] && center_output "密码: ${hotspot_password}   " "above"
                else
                    center_output "获取热点名和密码失败   " "not_exist"
                fi
                
                # 判断是否存在busybox
                if [[ ${is_busybox_exist} ]]; then
                    # 获取共享网络使用流量数
                    local flow="`ifconfig "${hotspots_net_card}" | grep 'TX bytes' | sed 's/.*TX bytes:.*(\(.*B\)).*/\1/;s/i.*//'`"
                    # 输出共享网络使用流量数
                    [[ "0.0 B" == ${flow} || ! ${flow} ]] && center_output "已用: 没查到 ×  " "above" || center_output "已用: ${flow}  " "above"
                fi
            fi
        fi
            
    fi
    
    # 获取小尾巴内容
    local output_tail="`echo "${configure_file_content#*小尾巴=}"`"
    # 输出小尾巴内容
    if [[ ${output_tail} ]]; then
        output_dividing_line "not_exist"
        
        echo "${output_tail}" | while read ZJL; do
            center_output "${ZJL}   " "above"
        done
    fi
    
    output_dividing_line
}


# 防跳主体部分 []<-(option...)
mainBody() {
    # 判断当前脚本执行状态
    if [[ `echo "${*}" | grep -E '(\-o)|(\-\-open)'` ]]; then
        script_execution_state="open"
        # 禁止网络
        iptables -I OUTPUT ! -o wlan+ -j DROP
        iptables -I FORWARD -j DROP
    elif [[ `echo "${*}" | grep -E '(\-c)|(\-\-close)'` ]]; then
        script_execution_state="close"
    fi
    
    # 初始化
    init_zjl
    
    # 判断初始化状态
    if [[ "1" == ${?} ]]; then
        # 关闭数据
        svc data disable
        # 释放网络
        iptables -D OUTPUT ! -o wlan+ -j DROP
        iptables -D FORWARD -j DROP
        # 退出脚本
        exit
    fi
    
    if [[ "open" == ${script_execution_state} ]]; then
        # 打开数据
        network_on_off "open"
        # 关闭防跳
        close_zjl
        # 打开防跳
        open_zjl
        
        local start_code="${?}"
        # 判断启动状态码 正常为0
        if [[ "0" != ${start_code} ]]; then
            # 关闭数据
            svc data disable
            local log_path="${0%/*}/start_error_log.txt"
            
            echo "开启核心 ${unlimited_data_way} 失败\n错误原因:" > ${log_path}
            
            if [[ "1" == ${start_code} ]]; then
                case ${mode_file_state} in
                    no_selected_mode_file)
                        echo "没找到指定的 ${select_mode_file}.conf 文件" >> ${log_path}
                    ;;
                    please_select)
                        echo "有多个模式文件 防跳不知道启动哪一个\n所以请使用 [选择模式] 功能 !" >> ${log_path}
                    ;;
                    no_content)
                        echo "模式内容为空 !" >> ${log_path}
                    ;;
                    no_mode_file)
                        echo "没找到模式 所以请添加模式文件 !" >> ${log_path}
                    ;;
                esac
            else
                echo "${core_start_error_info}" >> ${log_path}
            fi
        fi
        
        # 释放网络
        iptables -D OUTPUT ! -o wlan+ -j DROP
        iptables -D OUTPUT ! -o wlan+ -m owner ! --gid 3004 -j DROP
        iptables -D FORWARD -j DROP
        
    elif [[ "close" == ${script_execution_state} ]]; then
        # 关闭数据
        network_on_off "close"
        # 关闭防跳
        close_zjl
    fi
    
    # 判断是否显示界面
    [[ `echo "${*}" | grep -E '(\-d)|(\-\-display)'` ]] && show_display
}

# 主函数 []<-(option...)
main() {
    # 保存参数
    options="${*} "
    
    # 判断选项是否合法
    if [[ `echo "${options}" | grep -E "^((-[ocdihv][ ])|(--(open|kill|display|info|help|version)[ ])){1,3}$"` ]]; then
        if [[ `echo "${options}" | grep -E '(\-h)|(\-\-help)'` ]]; then
            [[ "1" == ${#} ]] && show_help || show_help "-h 或者 --help 只能单独使用"            
        elif [[ `echo "${options}" | grep -E '(\-v)|(\-\-version)'` ]]; then
            [[ "1" == ${#} ]] && echo "ZJL 防跳 ${zjl_version}" || show_help "-v 或者 --version 只能单独使用"            
        else
            # 显示帮助
            [[ `echo "${options}" | grep -E '(\-o)|(\-\-open)' | grep -E '(\-c)|(\-\-close)'` ]] && show_help "不可以同时执行开启和关闭，-o 和 -c 二选一"
        fi
    else
        # 显示帮助
        show_help "参数错误，只支持1-3个有效参数"
    fi  2>/dev/null
    
    # 判断是否显示错误输出
    [[ `echo "${options}" | grep -E '(\-i)|(\-\-info)'` ]] && mainBody ${*} || mainBody ${*} 2>/dev/null
}


# 调用主函数
main ${*}